#include <stdio.h>
#include <string.h>
#include "NetHelper.h"

#ifdef WIN32
#include <winsock2.h>
#include <mswsock.h>
#include <Ws2tcpip.h>
#else
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <unistd.h>
#include <errno.h>
#endif


// --
int NetworkStartup()
{
#ifdef WIN32
	WSADATA wsaData;
	WSAStartup(MAKEWORD(2,2), &wsaData);
#endif
	return 0;
}

int NetworkCleanup()
{
#ifdef WIN32
	WSACleanup();
#endif
	return 0;
}

// --
uint32_t str2ip(const char *ip)
{
	if(ip) {
		return inet_addr(ip);
	}
	return INADDR_NONE;
}

uint32_t str2ip(const std::string& ip)
{
	if(!ip.empty()) {
		return inet_addr(ip.c_str());
	}
	return INADDR_NONE;
}

std::string ip2str(uint32_t ip)
{
	ip = ntohl(ip);
	char buf[16];
	int len = sprintf(buf, "%d.%d.%d.%d", (ip>>24)&0xff, (ip>>16)&0xff, (ip>>8)&0xff, ip&0xff);
	return std::string(buf, len);
}

uint32_t net2host(uint32_t n)
{
	return ntohl(n);
}

uint16_t net2host(uint16_t n)
{
	return ntohs(n);
}

uint32_t host2net(uint32_t n)
{
	return htonl(n);
}

uint16_t host2net(uint16_t n)
{
	return htons(n);
}

bool IsValidAddr(uint32_t ip)
{
	return ip!=INADDR_NONE && ip!=INADDR_ANY;
}


//////////////////////////////////////////////////
//
DnsQuery::DnsQuery()
{
	m_ipcnt = 0; 
}

size_t DnsQuery::GetEntryCount() const
{
	return m_ipcnt;
}

uint32_t DnsQuery::GetAddress(size_t idx) const
{
	if(idx < m_ipcnt) {
		return m_ipaddr[idx];
	}
	return INADDR_NONE;
}

size_t DnsQuery::CopyTo(uint32_t ipbuf[], size_t ccb) const 
{
	size_t n = (m_ipcnt>ccb)?ccb:m_ipcnt;
	for(size_t i=0; i<n; ++i) {
		ipbuf[i] = m_ipaddr[i];
	}
	return n;
}

/**
 * DnsQuery::Query(const char *): 
 * RETURN VALUE:
 * 0 ---> no error and name is resolved successfully
 * non-zero --> error occurs
 */
int DnsQuery::Query(const char *name)
{
	int herrno = 0;
	m_ipcnt = 0;

	if(!name)
		return -1;

	struct addrinfo aiHints;
	memset(&aiHints, 0, sizeof(aiHints));
	aiHints.ai_family = PF_INET;
	aiHints.ai_socktype = SOCK_STREAM;
	aiHints.ai_protocol = IPPROTO_TCP;

	struct addrinfo *aiList = NULL;
	herrno = getaddrinfo(name, NULL, &aiHints, &aiList);
	if (herrno == 0) {
		const struct addrinfo *pa = aiList;
		while(pa && m_ipcnt<MAXENTRIES) {
			  struct sockaddr_in *psai = (struct sockaddr_in *)pa->ai_addr;
			  m_ipaddr[m_ipcnt++] = psai->sin_addr.s_addr;
			  pa = pa->ai_next;
		}
		freeaddrinfo(aiList);
		aiList = NULL;
	} //else failed to resolved

	if(m_ipcnt == 0)
		herrno = -1;

	return herrno;
}

//EOF
